<?php

namespace apiend\modules\dynamic\models;

use Yii;
use common\base\Model;
use yii\db\Exception;
use yii\helpers\Json;
use yii\helpers\ArrayHelper;
use common\helpers\StringHelper;
use common\models\dynamic\Dynamic;
use common\models\dynamic\DynamicGallery;
use common\models\Attachment;
use common\models\dynamic\DynamicTopic;
use common\models\dynamic\Topic;
use common\models\dynamic\TopicFilter;
use common\models\mongo\DynamicMess;
use common\models\dynamic\DynamicStats;

class DynamicForm extends Model {

    /**
     * @name $user_id
     * @var integer 用户UID
     */
    public $user_id;

    /**
     * @name $device_id
     * @var integer 用户设备ID
     */
    public $device_id;

    /**
     * @name $retweet_id
     * @var integer 转发动态ID
     */
    public $retweet_id = 0;

    /**
     * @name $content
     * @var string 动态内容
     */
    public $content;

    /**
     * @name $images
     * @var string 动态包含的图片集合，base64转义的json格式字符串
     */
    public $images;

    /**
     * @name $position
     * @var string 位置
     */
    public $position = '';

    /**
     * @name $format
     * @var integer 动态格式：0普通(图集)动态，1视频动态，2文章动态
     */
    public $format = Dynamic::FORMAT_DEFAULT;

    /**
     * @name $attachs
     * @var \common\models\Attachment 附件集合
     */
    private $attachs = null;

    /**
     * @name $pics
     * @var string 格式化后的图片集合
     */
    private $pics = [];
    public $topics;

    public function rules() {
        return [
            [['user_id', 'device_id', 'retweet_id', 'format'], 'integer'],
            [
                'content',
                'required',
                'when' => function ($model) {
                    return empty($model->images);
                },
                'message' => '{attribute}不能为空'
            ],
            ['content', 'string', 'max' => 1000],
            ['position', 'string', 'max' => 100],
            ['images', 'string'],
            ['images', 'formatImage'],
            ['content', 'validateContentForTopic']
        ];
    }

    /**
     * 格式化图集内容
     * This method serves as the inline validation for password.
     *
     * @param string $attribute the attribute currently being validated
     * @param array $params the additional name-value pairs given in the rule
     */
    public function formatImage($attribute) {
        if (!$this->hasErrors() && $this->$attribute) {
            $safeImages = base64_decode($this->$attribute);
            $pics = Json::decode($safeImages);
            $baseFormat = ['filename' => '', 'width' => 0, 'height' => 0];
            foreach ($pics as $key => $image) {
                if (!isset($image['filename']) || !$image['filename']) {
                    unset($pics[$key]);
                    continue;
                }
                $pics[$key] = ArrayHelper::merge($baseFormat, $image);
            }
            if (empty($pics) && !$this->content) {
                $this->addError('content', '动态内容不能为空');
            }
            $this->pics = $pics;
        }
    }

    /**
     * Validates the password.
     * This method serves as the inline validation for password.
     *
     * @param string $attribute the attribute currently being validated
     * @param array $params the additional name-value pairs given in the rule
     */
    public function validateAttachs($attribute) {
        if (!$this->hasErrors() && !empty($this->$attribute)) {
            $this->attachs = Attachment::find()->where(['id' => $this->$attribute])->all();
        }
    }

    /**
     * 过滤话题
     */
    public function validateContentForTopic($attribute) {
        if (!$this->hasErrors() && !empty($this->$attribute)) {
            $tag_pattern = "/\#([^\#|.]+)\#/";
            preg_match_all($tag_pattern, $this->content, $tagsarr);
            $topics = $tagsarr[1];
            $query = TopicFilter::find();

            foreach ($topics as $topic) {
                $query->orWhere(['content' => $topic]);
            }

            $errors = '';

            foreach ($query->all() as $item) {
                $errors .= ' #' . $item->content . '#';
            }

            if ($errors) {
                $errors = '这些话题不允许发布：' . $errors;
                $this->addError($attribute, $errors);
                return false;
            } else {
                $this->topics = $topics;
            }
            return true;
        }
    }

    /**
     * 保存动态信息（发布&修改）
     * @param [type] $data
     * @return void
     */
    public function save() {
        if (!$this->validate()) {
            return $this->dumpError('发布提交失败');
        }

        $model = new Dynamic();
        $model->attributes = [
            'user_id' => $this->user_id,
            'device_id' => $this->device_id,
            'content' => $this->content,
            'position' => $this->position,
            'retweet_id' => $this->retweet_id,
            'format' => $this->format,
        ];

        $transaction = Yii::$app->db->beginTransaction();
        try {
            if (!$model->save()) {
                throw new Exception('动态内容保存时失败');
            }
            $stats = DynamicStats::findOrNew([
                'dynamic_id' => $model->id,
                'comment_id' => 0,
            ]);
            if (!$stats->save()) {
                throw new Exception('动态创建初始化失败');
            }
            if ($this->images && !empty($this->pics)) {
                $gallery = new DynamicGallery();
                foreach ($this->pics as $listorder => $image) {
                    extract($image);
                    $_gallery = clone $gallery;
                    $_gallery->user_id = $this->user_id;
                    $_gallery->dynamic_id = $model->id;
                    $_gallery->listorder = $listorder;
                    $_gallery->original = $filename;
                    $_gallery->width = $width;
                    $_gallery->height = $height;
                    if (!$_gallery->save()) {
                        throw new Exception('图集保存失败');
                    }
                }
            }
            $transaction->commit();
        } catch (Exception $e) {
            $transaction->rollBack();
            return $this->dumpError($e->getMessage());
        }
        //话题匹配
        $this->relationTopic($model->id);
        //推送队列操作
        $this->pushQueue($this->content, $model->id);

        return $model->attributes;
    }

    protected function relationTopic($dynamicId) {
        if (empty($this->topics)) {
            return;
        }
        foreach ($this->topics as $topic) {
            $topicModel = Topic::findOne(['content' => $topic]);
            if (!$topicModel) {
                $topicModel = new Topic();
                $topicModel->content = $topic;
                $topicModel->is_official = Topic::OFFICIAL_Y;
                $topicModel->user_id = $this->user_id;
                $topicModel->join_nums = 1;
                $topicModel->weight = 0; //权重 暂时无公式
            } else {
                $topicModel->join_nums += 1;
            }
            $topicModel->save();

            $dynamicTopicModel = new DynamicTopic();
            $dynamicTopicModel->topic_id = $topicModel->id;
            $dynamicTopicModel->dynamic_id = $dynamicId;
            $dynamicTopicModel->topic_content = $topicModel->content;
            $dynamicTopicModel->save();
        }
    }

    /**
     * 推送队列操作
     * @return void
     */
    protected function pushQueue($content, $dynamicId) {
        $usernames = StringHelper::matchAt($content);
        Yii::$app->queue->push(new \common\jobs\DynamicMessageJob([
            'usernames' => $usernames,
            'active_input' => [
                'user_id' => $this->user_id,
                'dynamic_id' => $dynamicId
            ],
            'mess_type' => DynamicMess::MESS_TYPE_AT
        ]));
        //开发环境直接返回
        if (YII_ENV_DEV) {
            return;
        }
        //检测动态是否涉及@内容
        $usernames = StringHelper::matchAt($content);
        if (!empty($usernames)) {
            Yii::error([
                'usernames' => $usernames,
                'dynamic_id' => $dynamicId,
            ]);
            Yii::$app->queue->push(new \common\jobs\DynamicAtNoticeJob([
                'usernames' => $usernames,
                'dynamic_id' => $dynamicId,
            ]));
            Yii::$app->queue->push(new \common\jobs\DynamicMessageJob([
                'usernames' => $usernames,
                'active_input' => [
                    'user_id' => $this->user_id,
                    'dynamic_id' => $dynamicId
                ],
                'mess_type' => DynamicMess::MESS_TYPE_AT
            ]));
        }
        //检测动态内容是否匹配话题
        $topicnames = StringHelper::matchTopic($content);
        if (!empty($topicnames)) {
            Yii::$app->queue->push(new \common\jobs\DynamicJoinTopicJob([
                'topicnames' => $topicnames,
                'dynamic_id' => $dynamicId,
            ]));
        }

        if ($this->retweet_id) {
            $retweet = Dynamic::findOne($this->retweet_id);
            Yii::$app->queue->push(new \common\jobs\DynamicMessageJob([
                'active_input' => [
                    'user_id' => $this->user_id,
                    'dynamic_id' => $dynamicId
                ],
                'passive_input' => [
                    [
                        'user_id' => $retweet->user_id,
                        'dynamic_id' => $retweet->id,
                    ]
                ],
                'mess_type' => DynamicMess::MESS_TYPE_SEND
            ]));
        }
    }

}
